fplot_plot_data_bar.f90 Source File


Source Code

! fplot_plot_data_bar.f90

! TO DO:
! - Allow naming of each data set at the define_data level as well

module fplot_plot_data_bar
    use iso_fortran_env
    use fplot_plot_data
    use fplot_errors
    use fplot_colors
    use strings
    implicit none
    private
    public :: plot_data_bar

    type, extends(plot_data_colored) :: plot_data_bar
        !! Defines a data set tailored to bar charts.
        type(string), private, allocatable, dimension(:) :: m_axisLabels
            !! An array containing axis labels to associate with each bar.
        real(real64), private, allocatable, dimension(:,:) :: m_barData
            !! An array of data defining each bar - the matrix contains
            !! multiple columns to allow multiple bars per label.
        logical, private :: m_useAxisLabels = .true.
            !! Determines if the axis labels should be used - only applicable
            !! if there is existing data stored in m_axisLabels & m_axisLabels
            !! is the same size as m_barData.
        logical, private :: m_useY2 = .false.
            !! Draw against the secondary y axis?
        logical, private :: m_filled = .true.
            !! Determines if each bar is filled.
        real(real32), private :: m_alpha = 1.0
            !! The alpha value (transparency) for each bar.
        type(color), private, allocatable, dimension(:) :: m_barColors
            !! The color to use for each data series (column).  If not
            !! set, a default color cycle is used for multi-series data,
            !! or the base line color is used for single-series data.
        type(string), private, allocatable, dimension(:) :: m_seriesNames
            !! The legend title to associate with each data series (column).
    contains
        procedure, public :: get_count => pdb_get_count
        procedure, public :: get => pdb_get_data
        procedure, public :: set => pdb_set_data
        procedure, public :: get_data => pdb_get_data_set
        procedure, public :: get_label => pdb_get_label
        procedure, public :: set_label => pdb_set_label
        procedure, public :: get_use_labels => pdb_get_use_labels
        procedure, public :: set_use_labels => pdb_set_use_labels
        procedure, public :: get_command_string => pdb_get_cmd
        procedure, public :: get_data_string => pdb_get_data_cmd
        procedure, public :: get_axes_string => pdb_get_axes_cmd
        procedure, public :: get_bar_per_label_count => pdb_get_col_count
        procedure, public :: get_draw_against_y2 => pdb_get_use_y2
        procedure, public :: set_draw_against_y2 => pdb_set_use_y2
        procedure, public :: get_is_filled => pdb_get_is_filled
        procedure, public :: set_is_filled => pdb_set_is_filled
        procedure, public :: get_transparency => pdb_get_alpha
        procedure, public :: set_transparency => pdb_set_alpha
        procedure, public :: get_bar_color => pdb_get_bar_color
        procedure, public :: set_bar_color => pdb_set_bar_color
        procedure, public :: get_series_name => pdb_get_series_name
        procedure, public :: set_series_name => pdb_set_series_name
        generic, public :: define_data => pdb_set_data_1, pdb_set_data_2, &
            pdb_set_data_3, pdb_set_data_4, pdb_set_data_5, pdb_set_data_6
        procedure, private :: pdb_set_data_1
        procedure, private :: pdb_set_data_2
        procedure, private :: pdb_set_data_3
        procedure, private :: pdb_set_data_4
        procedure, private :: pdb_set_data_5
        procedure, private :: pdb_set_data_6
        procedure, public :: set_data_1 => pdb_set_data_1_core
        procedure, public :: set_data_2 => pdb_set_data_2_core
        procedure, public :: set_data_3 => pdb_set_data_3_core
        procedure, public :: set_data_4 => pdb_set_data_4_core
        procedure, public :: set_data_5 => pdb_set_data_5_core
        procedure, public :: set_data_6 => pdb_set_data_6_core
        procedure, public :: clear_data => pdb_clear_data
    end type

contains
! ------------------------------------------------------------------------------
pure function pdb_get_count(this) result(x)
    !!  Gets the number of stored data points.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    integer(int32) :: x
        !! The number of stored data points.
    if (allocated(this%m_barData)) then
        x = size(this%m_barData, 1)
    else
        x = 0
    end if
end function

! ------------------------------------------------------------------------------
pure function pdb_get_data(this, index, col) result(x)
    !! Gets the requested data point.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    integer(int32), intent(in) :: index
        !! The data point index.
    integer(int32), intent(in) :: col
        !! The column index.
    real(real64) :: x
        !! The value.
    if (allocated(this%m_barData)) then
        x = this%m_barData(index, col)
    else
        x = 0.0d0
    end if
end function

! ------------------------------------------------------------------------------
subroutine pdb_set_data(this, index, col, x)
    !! Replaces the requested data point.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    integer(int32), intent(in) :: index
        !! The data point index.
    integer(int32), intent(in) :: col
        !! The column index.
    real(real64), intent(in) :: x
        !! The new value.
    if (allocated(this%m_barData)) then
        this%m_barData(index, col) = x
    end if
end subroutine

! ------------------------------------------------------------------------------
pure function pdb_get_data_set(this, col) result(x)
    !! Gets the requested data set.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    integer(int32), intent(in) :: col
        !! The column index.
    real(real64), allocatable, dimension(:) :: x
        !! A copy of the data set.
    if (allocated(this%m_barData)) then
        x = this%m_barData(:,col)
    else
        allocate(x(0))
    end if
end function

! ------------------------------------------------------------------------------
pure function pdb_get_label(this, index) result(x)
    !! Gets the axis label associated with a specific data set.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    integer(int32), intent(in) :: index
        !! The index of the data set.
    character(len = :), allocatable :: x
        !! The label.
    if (allocated(this%m_axisLabels)) then
        x = char(this%m_axisLabels(index))
    else
        x = ""
    end if
end function

! ------------------------------------------------------------------------------
subroutine pdb_set_label(this, index, txt)
    !! Sets the axis label for a specific data set.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    integer(int32) :: index
        !! The index of the data set.
    character(len = *), intent(in) :: txt
        !! The label.
    if (allocated(this%m_axisLabels)) then
        this%m_axisLabels(index) = txt
    end if
end subroutine

! ------------------------------------------------------------------------------
pure function pdb_get_use_labels(this) result(x)
    !! Gets a value determining if labels are used to identify the data.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    logical :: x
        !! Returns true if labels are used; else, false.
    x = this%m_useAxisLabels
end function

! ------------------------------------------------------------------------------
subroutine pdb_set_use_labels(this, x)
    !! Sets a value determining if labels are used to identify the data.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    logical, intent(in) :: x
        !! Set to true if labels are used; else, false.
    this%m_useAxisLabels = x
end subroutine

! ------------------------------------------------------------------------------
function pdb_get_cmd(this) result(x)
    !! Gets the GNUPLOT command string for this object.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    character(len = :), allocatable :: x
        !! The command string.

    ! Local Variables
    type(string_builder) :: str
    integer(int32) :: j, ncols, offset
    logical :: uselabels
    character(len = :), allocatable :: title
    type(color) :: clr

    ! Initialization
    call str%initialize()
    ncols = max(this%get_bar_per_label_count(), 1)
    uselabels = this%get_use_labels() .and. allocated(this%m_barData) .and. &
        allocated(this%m_axisLabels)
    if (uselabels) then
        offset = 1
    else
        offset = 0
    end if

    ! Each data series (column) is drawn with its own "using" clause so
    ! that multiple bar series stored in a single datablock all appear
    do j = 1, ncols
        if (j > 1) call str%append(", ")

        ! Data Block
        call str%append(" $")
        call str%append(this%get_datablock_name())
        call str%append(" using ")
        call str%append(to_string(j + offset))
        if (j == 1 .and. uselabels) call str%append(":xtic(1)")

        ! Filled?
        if (this%get_is_filled()) then
            call str%append(" fill solid ")
        else
            call str%append(" fill empty ")
        end if

        ! Transparency
        call str%append(to_string(this%get_transparency()))

        ! Title
        title = this%get_series_name(j)
        if (len_trim(title) == 0 .and. ncols == 1) title = this%get_name()
        if (len_trim(title) > 0) then
            call str%append(' title "')
            call str%append(title)
            call str%append('"')
        else
            call str%append(' notitle')
        end if

        ! Color
        clr = this%get_bar_color(j)
        call str%append(' lc rgb "#')
        call str%append(clr%to_hex_string())
        call str%append('"')

        ! Define the axes structure
        call str%append(" ")
        call str%append(this%get_axes_string())
    end do

    ! End
    x = char(str%to_string())
end function

! ------------------------------------------------------------------------------
function pdb_get_data_cmd(this) result(x)
    !! Gets the GNUPLOT command string defining the data for this object.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    character(len = :), allocatable :: x
        !! The command string.

    ! Local Variables
    type(string_builder) :: str
    integer(int32) :: i, j, nbars, ncols
    character :: delimiter, nl

    ! Initialization
    call str%initialize()
    delimiter = achar(9)
    nl = new_line(nl)
    nbars = this%get_count()
    ncols = this%get_bar_per_label_count()

    ! Process
    if (this%get_use_labels() .and. allocated(this%m_axisLabels) .and. &
            allocated(this%m_barData)) then
        do i = 1, nbars
            call str%append(char(this%m_axisLabels(i)))
            call str%append(delimiter)
            do j = 1, ncols
                call str%append(to_string(this%get(i, j)))
                if (j /= ncols) call str%append(delimiter)
            end do
            call str%append(nl)
        end do
    else
        do i = 1, nbars
            do j = 1, ncols
                call str%append(to_string(this%get(i, j)))
                if (j /= ncols) call str%append(delimiter)
            end do
            call str%append(nl)
        end do
    end if

    ! End
    x = char(str%to_string())
end function

! ------------------------------------------------------------------------------
function pdb_get_axes_cmd(this) result(x)
    !! Gets the GNUPLOT command defining which axes to plot against.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    character(len = :), allocatable :: x
        !! The command string.

    ! Define which axes the data is to be plotted against
    if (this%get_draw_against_y2()) then
        x = "axes x1y2"
    else
        x = "axes x1y1"
    end if
end function

! ------------------------------------------------------------------------------
pure function pdb_get_col_count(this) result(x)
    !! Gets the number of data sets (columns).
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    integer(int32) :: x
        !! The count.
    if (allocated(this%m_barData)) then
        x = size(this%m_barData, 2)
    else
        x = 0
    end if
end function

! ------------------------------------------------------------------------------
pure function pdb_get_use_y2(this) result(x)
    !! Gets a value determining if the data should be plotted against a
    !! secondary y-axis.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    logical :: x
        !! Returns true to plot against a secondary y-axis; else, false.
    x = this%m_useY2
end function

! ------------------------------------------------------------------------------
subroutine pdb_set_use_y2(this, x)
    !! Sets a value determining if the data should be plotted against a
    !! secondary y-axis.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    logical, intent(in) :: x
        !! Set to true to plot against a secondary y-axis; else, false.
    this%m_useY2 = x
end subroutine

! ------------------------------------------------------------------------------
pure function pdb_get_bar_color(this, index) result(x)
    !! Gets the color to use for the requested data series (column).  If
    !! no color has been explicitly set, a default color cycle is used
    !! for multi-series data, or the base line color for single-series
    !! data.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    integer(int32), intent(in) :: index
        !! The index of the data series (column).
    type(color) :: x
        !! The color.

    if (allocated(this%m_barColors)) then
        if (index >= 1 .and. index <= size(this%m_barColors)) then
            x = this%m_barColors(index)
            return
        end if
    end if

    if (this%get_bar_per_label_count() <= 1) then
        x = this%get_line_color()
    else
        x = color_list(mod(index - 1, size(color_list)) + 1)
    end if
end function

! ------------------------------------------------------------------------------
subroutine pdb_set_bar_color(this, index, x)
    !! Sets the color to use for the requested data series (column).
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    integer(int32), intent(in) :: index
        !! The index of the data series (column).
    type(color), intent(in) :: x
        !! The color.

    ! Local Variables
    type(color), allocatable, dimension(:) :: temp
    integer(int32) :: i, n

    n = max(index, this%get_bar_per_label_count())
    if (.not.allocated(this%m_barColors)) then
        allocate(this%m_barColors(n))
        do i = 1, n
            this%m_barColors(i) = this%get_bar_color(i)
        end do
    else if (size(this%m_barColors) < n) then
        allocate(temp(n))
        do i = 1, n
            if (i <= size(this%m_barColors)) then
                temp(i) = this%m_barColors(i)
            else
                temp(i) = this%get_bar_color(i)
            end if
        end do
        call move_alloc(temp, this%m_barColors)
    end if
    this%m_barColors(index) = x
end subroutine

! ------------------------------------------------------------------------------
pure function pdb_get_series_name(this, index) result(x)
    !! Gets the legend title associated with the requested data series
    !! (column).
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    integer(int32), intent(in) :: index
        !! The index of the data series (column).
    character(len = :), allocatable :: x
        !! The title.

    if (allocated(this%m_seriesNames)) then
        if (index >= 1 .and. index <= size(this%m_seriesNames)) then
            x = char(this%m_seriesNames(index))
            return
        end if
    end if
    x = ""
end function

! ------------------------------------------------------------------------------
subroutine pdb_set_series_name(this, index, txt)
    !! Sets the legend title to associate with the requested data series
    !! (column).
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    integer(int32), intent(in) :: index
        !! The index of the data series (column).
    character(len = *), intent(in) :: txt
        !! The title.

    ! Local Variables
    type(string), allocatable, dimension(:) :: temp
    integer(int32) :: i, n

    n = max(index, this%get_bar_per_label_count())
    if (.not.allocated(this%m_seriesNames)) then
        allocate(this%m_seriesNames(n))
    else if (size(this%m_seriesNames) < n) then
        allocate(temp(n))
        do i = 1, size(this%m_seriesNames)
            temp(i) = this%m_seriesNames(i)
        end do
        call move_alloc(temp, this%m_seriesNames)
    end if
    this%m_seriesNames(index) = txt
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_1(this, x, err)
    !! Defines a single data set.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    real(real64), intent(in), dimension(:) :: x
        !! The data to plot.
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Process
    call this%set_data_1(x, err)
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_2(this, labels, x, err)
    !! Defines data along with associated axis labels.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    class(string), intent(in), dimension(:) :: labels
        !! The axis labels to associate with the data.
    real(real64), intent(in), dimension(:) :: x
        !! The data set.
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Process
    call this%set_data_2(labels, x, err)
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_3(this, labels, x, fmt, err)
    !! Defines data along with labels and formatting information.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    real(real64), intent(in), dimension(:) :: labels
        !! The axis labels to associate with the data.
    real(real64), intent(in), dimension(:) :: x
        !! The data set.
    character(len = *), intent(in), optional :: fmt
        !! The format string for the labels (e.g. '(I0)', etc.).
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Process
    call this%set_data_3(labels, x, fmt, err)
end subroutine

! ------------------------------------------------------------------------------
pure function pdb_get_is_filled(this) result(x)
    !! Gets a value determining if each bar is filled.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    logical :: x
        !! Returns true if the bars are to be filled; else, false.
    x = this%m_filled
end function

! ------------------------------------------------------------------------------
subroutine pdb_set_is_filled(this, x)
    !! Sets a value determining if each bar is filled.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    logical, intent(in) :: x
        !! Set to true if the bars are to be filled; else, false.
    this%m_filled = x
end subroutine

! ------------------------------------------------------------------------------
pure function pdb_get_alpha(this) result(x)
    !! Gets the alpha (transparency) for the bar color.
    class(plot_data_bar), intent(in) :: this
        !! The plot_data_bar object.
    real(real32) :: x
        !! The alpha value ([0, 1]).
    x = this%m_alpha
end function

! ------------------------------------------------------------------------------
subroutine pdb_set_alpha(this, x)
    !! Gets the alpha (transparency) for the bar color.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    real(real32), intent(in) :: x
        !! The alpha value ([0, 1]).
    if (x > 1.0) then
        this%m_alpha = 1.0
    else if (x < 0.0) then
        this%m_alpha = 0.0
    else
        this%m_alpha = x
    end if
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_1_core(this, x, err)
    !! Defines the data set.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    real(real64), intent(in), dimension(:) :: x
        !! The data set.
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Local Variables
    class(errors), pointer :: errmgr
    type(errors), target :: deferr
    integer(int32) :: n, flag
    
    ! Initialization
    if (present(err)) then
        errmgr => err
    else
        errmgr => deferr
    end if
    n = size(x)

    if (len(this%get_datablock_name()) == 0) then
        call this%create_unique_datablock_name()
    end if

    ! Process
    if (allocated(this%m_axisLabels)) deallocate(this%m_axisLabels)
    if (allocated(this%m_barData)) deallocate(this%m_barData)
    allocate(this%m_barData(n, 1), stat = flag)
    if (flag /= 0) then
        call report_memory_error(errmgr, "pdb_set_data_1_core", flag)
        return
    end if
    this%m_barData(:,1) = x
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_2_core(this, labels, x, err)
    ! Arguments
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    class(string), intent(in), dimension(:) :: labels
        !! The axis labels.
    real(real64), intent(in), dimension(:) :: x
        !! The data set.
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Local Variables
    class(errors), pointer :: errmgr
    type(errors), target :: deferr
    integer(int32) :: n, flag
    
    ! Initialization
    if (present(err)) then
        errmgr => err
    else
        errmgr => deferr
    end if
    n = size(x)

    if (len(this%get_datablock_name()) == 0) then
        call this%create_unique_datablock_name()
    end if

    ! Input Check
    if (size(labels) /= n) then
        call report_array_size_mismatch_error(errmgr, "pdb_set_data_2_core", &
            "labels", n, size(labels))
        return
    end if

    ! Process
    if (allocated(this%m_axisLabels)) deallocate(this%m_axisLabels)
    if (allocated(this%m_barData)) deallocate(this%m_barData)
    allocate(this%m_barData(n, 1), stat = flag)
    if (flag == 0) allocate(this%m_axisLabels(n), stat = flag)
    if (flag /= 0) then
        call report_memory_error(errmgr, "pdb_set_data_2_core", flag)
        return
    end if
    this%m_barData(:,1) = x
    this%m_axisLabels = labels
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_3_core(this, labels, x, fmt, err)
    ! Arguments
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    real(real64), intent(in), dimension(:) :: labels
        !! The axis labels.
    real(real64), intent(in), dimension(:) :: x
        !! The data set.
    character(len = *), intent(in), optional :: fmt
        !! The format string for the labels (e.g. '(I0)', etc.).
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Local Variables
    class(errors), pointer :: errmgr
    type(errors), target :: deferr
    integer(int32) :: i, n, flag
    type(string), allocatable, dimension(:) :: lbls
    
    ! Initialization
    if (present(err)) then
        errmgr => err
    else
        errmgr => deferr
    end if
    n = size(x)

    if (len(this%get_datablock_name()) == 0) then
        call this%create_unique_datablock_name()
    end if

    ! Input Check
    if (size(labels) /= n) then
        call report_array_size_mismatch_error(errmgr, "pdb_set_data_3_core", &
            "labels", n, size(labels))
        return
    end if

    ! Convert the numeric labels to strings
    allocate(lbls(n), stat = flag)
    if (flag /= 0) then
        call report_memory_error(errmgr, "pdb_set_data_3_core", flag)
        return
    end if
    do i = 1, n
        lbls(i) = to_string(labels(i), fmt)
    end do

    ! Store the data
    if (allocated(this%m_axisLabels)) deallocate(this%m_axisLabels)
    if (allocated(this%m_barData)) deallocate(this%m_barData)
    allocate(this%m_barData(n, 1), stat = flag)
    if (flag == 0) allocate(this%m_axisLabels(n), stat = flag)
    if (flag /= 0) then
        call report_memory_error(errmgr, "pdb_set_data_3_core", flag)
        return
    end if
    this%m_barData(:,1) = x
    this%m_axisLabels = lbls
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_clear_data(this)
    !! Clears the data from this data set.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    if (allocated(this%m_axisLabels)) deallocate(this%m_axisLabels)
    if (allocated(this%m_barData)) deallocate(this%m_barData)
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_4_core(this, x, err)
    !! Defines the data set.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    real(real64), intent(in), dimension(:,:) :: x
        !! The data set.
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Local Variables
    class(errors), pointer :: errmgr
    type(errors), target :: deferr
    integer(int32) :: flag
    
    ! Initialization
    if (present(err)) then
        errmgr => err
    else
        errmgr => deferr
    end if

    if (len(this%get_datablock_name()) == 0) then
        call this%create_unique_datablock_name()
    end if

    ! Process
    if (allocated(this%m_axisLabels)) deallocate(this%m_axisLabels)
    if (allocated(this%m_barData)) deallocate(this%m_barData)
    allocate(this%m_barData(size(x,1), size(x,2)), stat = flag, source = x)
    if (flag /= 0) then
        call report_memory_error(errmgr, "pdb_set_data_4_core", flag)
        return
    end if
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_5_core(this, labels, x, err)
    ! Arguments
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    class(string), intent(in), dimension(:) :: labels
        !! The axis labels.
    real(real64), intent(in), dimension(:,:) :: x
        !! The data set.
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Local Variables
    class(errors), pointer :: errmgr
    type(errors), target :: deferr
    integer(int32) :: n, flag
    
    ! Initialization
    if (present(err)) then
        errmgr => err
    else
        errmgr => deferr
    end if
    n = size(x, 1)

    if (len(this%get_datablock_name()) == 0) then
        call this%create_unique_datablock_name()
    end if

    ! Input Check
    if (size(labels) /= n) then
        call report_array_size_mismatch_error(errmgr, "pdb_set_data_5_core", &
            "labels", n, size(labels))
        return
    end if

    ! Process
    if (allocated(this%m_axisLabels)) deallocate(this%m_axisLabels)
    if (allocated(this%m_barData)) deallocate(this%m_barData)
    allocate(this%m_barData(size(x,1), size(x,2)), stat = flag, source = x)
    if (flag == 0) allocate(this%m_axisLabels(n), stat = flag)
    if (flag /= 0) then
        call report_memory_error(errmgr, "pdb_set_data_5_core", flag)
        return
    end if
    this%m_axisLabels = labels
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_6_core(this, labels, x, fmt, err)
    ! Arguments
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    real(real64), intent(in), dimension(:) :: labels
        !! The axis labels.
    real(real64), intent(in), dimension(:,:) :: x
        !! The data set.
    character(len = *), intent(in), optional :: fmt
        !! The format string for the labels (e.g. '(I0)', etc.).
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Local Variables
    class(errors), pointer :: errmgr
    type(errors), target :: deferr
    integer(int32) :: i, n, flag
    type(string), allocatable, dimension(:) :: lbls
    
    ! Initialization
    if (present(err)) then
        errmgr => err
    else
        errmgr => deferr
    end if
    n = size(x, 1)

    if (len(this%get_datablock_name()) == 0) then
        call this%create_unique_datablock_name()
    end if

    ! Input Check
    if (size(labels) /= n) then
        call report_array_size_mismatch_error(errmgr, "pdb_set_data_6_core", &
            "labels", n, size(labels))
        return
    end if

    ! Convert the numeric labels to strings
    allocate(lbls(n), stat = flag)
    if (flag /= 0) then
        call report_memory_error(errmgr, "pdb_set_data_6_core", flag)
        return
    end if
    do i = 1, n
        lbls(i) = to_string(labels(i), fmt)
    end do

    ! Store the data
    if (allocated(this%m_axisLabels)) deallocate(this%m_axisLabels)
    if (allocated(this%m_barData)) deallocate(this%m_barData)
    allocate(this%m_barData(size(x,1), size(x,2)), stat = flag, source = x)
    if (flag == 0) allocate(this%m_axisLabels(n), stat = flag)
    if (flag /= 0) then
        call report_memory_error(errmgr, "pdb_set_data_6_core", flag)
        return
    end if
    this%m_axisLabels = lbls
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_4(this, x, err)
    !! Defines a single data set.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    real(real64), intent(in), dimension(:,:) :: x
        !! The data to plot.
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Process
    call this%set_data_4(x, err)
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_5(this, labels, x, err)
    !! Defines data along with associated axis labels.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    class(string), intent(in), dimension(:) :: labels
        !! The axis labels to associate with the data.
    real(real64), intent(in), dimension(:,:) :: x
        !! The data set.
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Process
    call this%set_data_5(labels, x, err)
end subroutine

! ------------------------------------------------------------------------------
subroutine pdb_set_data_6(this, labels, x, fmt, err)
    !! Defines data along with labels and formatting information.
    class(plot_data_bar), intent(inout) :: this
        !! The plot_data_bar object.
    real(real64), intent(in), dimension(:) :: labels
        !! The axis labels to associate with the data.
    real(real64), intent(in), dimension(:,:) :: x
        !! The data set.
    character(len = *), intent(in), optional :: fmt
        !! The format string for the labels (e.g. '(I0)', etc.).
    class(errors), intent(inout), optional, target :: err
        !! An error handling object.

    ! Process
    call this%set_data_6(labels, x, fmt, err)
end subroutine

! ------------------------------------------------------------------------------
end module